/**
 * 微信支付回调服务
 */
import { Builder, parseString, convertableToString, OptionsV2 } from 'xml2js';
import { ICommonParams } from '@feidao/service/interfaces';
import log from '@feidao/web/atom/nodejs/logger/log';

interface IXmlJson {
	xml: IWxMsg;
}

interface IWxMsg {
	return_code: string; // 返回状态码	必填	描述：SUCCESS/FAIL
	return_msg: string; // 返回信息 必填	描述：OK	当return_code为FAIL时返回信息为错误原因 ，例如	签名失败 参数格式校验错误
	attach: string; // 附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用。
	// 以下字段在return_code为SUCCESS的时候有返回
	appid: string; // 公众账号ID 必填 描述：调用接口提交的公众账号ID
	mch_id: string;// 商户号 必填 描述：调用接口提交的商户号
	device_info: string;// 设备号 非必填 描述：自定义参数，可以为请求支付的终端设备号等
	nonce_str: string;// 随机字符串	 必填 描述：微信返回的随机字符串
	openid: string;// 公众账号ID 必填 描述：调用接口提交的公众账号ID
	sign: string;// 签名 必填 描述：微信返回的签名值，详见签名算法
	sign_type: string;// 签名类型，目前支持HMAC-SHA256和MD5，默认为MD5
	result_code: string;// 业务结果	 必填 描述：SUCCESS/FAIL
	err_code: string;// 错误代码	 非必填 描述：当result_code为FAIL时返回错误代码，详细参见下文错误列表
	err_code_des: string;// 错误代码描述	 非必填 描述：当result_code为FAIL时返回错误描述，详细参见下文错误列表
	is_subscribe: string; // 用户是否关注公众账号，Y-关注，N-未关注
	bank_type: string;// 银行类型，采用字符串类型的银行标识，银行类型见银行列表
	total_fee: number;// 订单总金额，单位为分
	settlement_total_fee: number;// 应结订单金额=订单金额-非充值代金券金额，应结订单金额<=订单金额。
	fee_type: string;// 货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
	cash_fee: number;// 现金支付金额订单现金支付金额，详见支付金额
	cash_fee_type: string;// 货币类型，符合ISO4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
	coupon_fee: string;// 代金券金额<=订单金额，订单金额-代金券金额=现金支付金额，详见支付金额
	coupon_count: number;// 代金券使用数量
	coupon_type_$n: string;// CASH--充值代金券 	NO_CASH---非充值代金券	并且订单使用了免充值券后有返回（取值：CASH、NO_CASH）。$n为下标,从0开始编号，举例：coupon_type_0
	coupon_id_$n: string;// 代金券ID,$n为下标，从0开始编号
	coupon_fee_$n: number;// 单个代金券支付金额,$n为下标，从0开始编号
	transaction_id: string;// 微信支付订单号
	out_trade_no: string;// 商户系统内部订单号，要求32个字符内，只能是数字、大小写字母_-|*@ ，且在同一个商户号下唯一。
	time_end: string;// 支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
	// 以下字段在return_code 和result_code都为SUCCESS的时候有返回
	trade_type: string;// 交易类型	 必填 描述：JSAPI 公众号支付	NATIVE 扫码支付	APP APP支付	说明详见参数规定
	prepay_id: string;// 预支付交易会话标识 必填 描述：微信生成的预支付会话标识，用于后续接口调用中使用，该值有效期为2小时
	code_url: string;// 二维码链接 非必填 描述：trade_type为NATIVE时有返回，用于生成二维码，展示给用户进行扫码支付
}

interface IAttach {
	sessionid: string;
	spaceid: string;
	flag: string;
}

/**
 * 将xml转为json
 * @param xml_str
 * @param options
 */
function xml2json(xml_str: convertableToString, options: OptionsV2) {
	return new Promise<IXmlJson>((resolve, reject) => {
		parseString(xml_str, options, (err, result) => {
			if (err) {
				const err_msg = (err && err.toString()) || 'unknow';
				log(`parse xml:${xml_str}.error msg: ${err_msg}`);
				reject(err_msg);
			} else {
				resolve(result);
			}
		});
	});
}

/**
 * 将json转为xml
 * @param obj
 * @param options
 */
function json2xml(obj: any, options: OptionsV2) {
	const builder = new Builder(options);
	const xml_result = builder.buildObject(obj);
	return xml_result;
}

// 支付处理
async function pay_process(xml: IXmlJson, attach: IAttach, _spaceid: string) {
	// todo 做支付处理
}

export default async function atom(msg: ICommonParams, action_id: string, session_id: string, _spaceid: string) {
	log('coming params is --:');
	log(JSON.stringify(msg));
	// {"body":{},"cookie":{},"data":"<xml><appid><![CDATA[wx76be1f60d92a519e]]></appid>\n<attach><![CDATA[{}]]></attach>\n<bank_type><![CDATA[CFT]]></bank_type>\n<cash_fee><![CDATA[1]]></cash_fee>\n<fee_type><![CDATA[CNY]]></fee_type>\n<is_subscribe><![CDATA[N]]></is_subscribe>\n<mch_id><![CDATA[1482927352]]></mch_id>\n<nonce_str><![CDATA[0913226866]]></nonce_str>\n<openid><![CDATA[ocZ-94hEHDgjJLjuqOSb04QUND5c]]></openid>\n<out_trade_no><![CDATA[201812110102658010]]></out_trade_no>\n<result_code><![CDATA[SUCCESS]]></result_code>\n<return_code><![CDATA[SUCCESS]]></return_code>\n<sign><![CDATA[89FCEF2EB03AEF474A31920CCDE43B3C]]></sign>\n<time_end><![CDATA[20181213091336]]></time_end>\n<total_fee>1</total_fee>\n<trade_type><![CDATA[JSAPI]]></trade_type>\n<transaction_id><![CDATA[4200000200201812137400015929]]></transaction_id>\n</xml>","headers":{"accept":"*/*","connection":"Keep-Alive","pragma":"no-cache","content-length":"789","host":"61.163.79.140","user-agent":"Mozilla/4.0","content-type":"text/xml"},"params":{},"query":{},"remote_address":"::ffff:140.207.54.76","url":"/wx-payfinish","modelid":"custom::js_wx-payfinish-mes","spaceid":"feidao_mes"}

	const params = msg.data;
	log('receive msg from wx:');
	log(JSON.stringify(params));
	// "<xml><appid><![CDATA[wx76be1f60d92a519e]]></appid>\n<attach><![CDATA[{}]]></attach>\n<bank_type><![CDATA[CFT]]></bank_type>\n<cash_fee><![CDATA[1]]></cash_fee>\n<fee_type><![CDATA[CNY]]></fee_type>\n<is_subscribe><![CDATA[N]]></is_subscribe>\n<mch_id><![CDATA[1482927352]]></mch_id>\n<nonce_str><![CDATA[0913226866]]></nonce_str>\n<openid><![CDATA[ocZ-94hEHDgjJLjuqOSb04QUND5c]]></openid>\n<out_trade_no><![CDATA[201812110102658010]]></out_trade_no>\n<result_code><![CDATA[SUCCESS]]></result_code>\n<return_code><![CDATA[SUCCESS]]></return_code>\n<sign><![CDATA[89FCEF2EB03AEF474A31920CCDE43B3C]]></sign>\n<time_end><![CDATA[20181213091336]]></time_end>\n<total_fee>1</total_fee>\n<trade_type><![CDATA[JSAPI]]></trade_type>\n<transaction_id><![CDATA[4200000200201812137400015929]]></transaction_id>\n</xml>"

	try {
		log('xml to json start');
		const data = await xml2json(params, { explicitArray: false });
		log(`xml to json end --data = ${JSON.stringify(data)}`);
		// {"xml":{"appid":"wx76be1f60d92a519e","attach":"{}","bank_type":"CFT","cash_fee":"1","fee_type":"CNY","is_subscribe":"N","mch_id":"1482927352","nonce_str":"0913226866","openid":"ocZ-94hEHDgjJLjuqOSb04QUND5c","out_trade_no":"201812110102658010","result_code":"SUCCESS","return_code":"SUCCESS","sign":"89FCEF2EB03AEF474A31920CCDE43B3C","time_end":"20181213091336","total_fee":"1","trade_type":"JSAPI","transaction_id":"4200000200201812137400015929"}}
		const attach = JSON.parse(data.xml.attach);
		const spaceid = params.spaceid || attach.spaceid || _spaceid;
		// todo 逻辑处理
		pay_process(data, attach, spaceid);

		log(`get pay attach data, attach = ${JSON.stringify(attach)}`);
		const res = `
<xml>
  <return_code>SUCCESS</return_code>
  <return_msg>OK</return_msg>
</xml>
		`;
		log(`微信返回信息！${res}`);
		return { data: res };
		// return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
	} catch (err) {
		const err_msg = (err && err.toString()) || 'unknow';
		log(`微信回调执行异常！${err_msg}`);
		// return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[' + err_msg + ']]></return_msg></xml>';
		const res = `
<xml>
  <return_code>SUCCESS</return_code>
  <return_msg>${err_msg}</return_msg>
</xml>
		`;
		return { data: res };
	}
}
